<?php
namespace app\common\dao;

use app\common\model\BaseModel;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;

abstract class BaseDao
{
    abstract protected function getModel(): string;

    public function getPk()
    {
        return ($this->getModel())::tablePk();
    }

    public function exists(int $id)
    {
        return $this->fieldExists($this->getPk(), $id);
    }

    public function fieldExists($field, $value, ?int $except = null, string $suffix = ''): bool
    {
        $query = ($this->getModel())::getDB($suffix)->where($field, $value);
        if (!is_null($except)) $query->where($this->getPk(), '<>', $except);
        return $query->count() > 0;
    }

    public function create(array $data, string $suffix = '')
    {
        return ($this->getModel())::create($data, [], false, $suffix);
    }

    public function update(int $id, array $data, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($this->getPk(), $id)->update($data);
    }

    public function updates(array $ids, array $data, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->whereIn($this->getPk(), $ids)->update($data);
    }

    public function updateByWhere(array $where, array $data, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($where)->update($data);
    }

    public function delete(int $id, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($this->getPk(), $id)->delete();
    }

    public function get($id, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->find($id);
    }

    public function getByWhere(array $where, string $field = '*', array $with = [], string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($where)->when($with, function ($query) use ($with) {
            $query->with($with);
        })->field($field)->find();
    }

    public function selectByWhere(array $where, string $field = '*', string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($where)->field($field)->select();
    }

    public function getWith(int $id, $with = [], string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->with($with)->find($id);
    }

    public function insertAll(array $data, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->insertAll($data);
    }

    public function getByWhereCount(array $where, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($where)->count();
    }

    public function existsByWhere($where, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($where)->count() > 0;
    }

    public function findAndAdd(array $where, string $suffix = '')
    {
       $res = ($this->getModel())::getDB($suffix)->where($where)->find();
       if(!$res)$res = $this->getModel()::create($where);
       return $res;
    }

    public function incField(int $id, string $field , $num = 1, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)->where($this->getPk(),$id)->inc($field,$num)->update();
    }

    public function decField(int $id, string $field , $num = 1, string $suffix = '')
    {
        return ($this->getModel())::getDB($suffix)
            ->where($this->getPk(),$id)
            ->where($field, '>=' ,$num)
            ->dec($field,$num)->update();
    }

    public function column(array $where, string $field = '', string $key = '', string $suffix = '')
    {
        if ($key) {
            return ($this->getModel())::getDB($suffix)->where($where)->column($field, $key);
        }
        return ($this->getModel())::getDB($suffix)->where($where)->column($field);
    }

    public function count(array $where, string $suffix = ''): int
    {
        return ($this->getModel())::getDB($suffix)->where($where)->count();
    }

    public function value(array $where,string $field, string $suffix = ''): int
    {
        return ($this->getModel())::getDB($suffix)->where($where)->value($field);
    }
}
